package netty.server;

import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import netty.model.MethodInvokeMeta;
import netty.model.NullWritable;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Component
public class RequestDispatcher implements ApplicationContextAware
{
	private ExecutorService executorService = Executors.newFixedThreadPool(1024);

	private ApplicationContext app;

	public void dispatcher(final ChannelHandlerContext ctx, final MethodInvokeMeta invokeMeta)
	{
		executorService.submit(new Runnable()
		{
			public void run()
			{
				ChannelFuture f = null;
				try
				{
					Class<?> interfaceClass = invokeMeta.getInterfaceClass();
					String name = invokeMeta.getName();
					Object[] args = invokeMeta.getArgs();
					Class<?>[] parameterTypes = invokeMeta.getParameterTypes();
					Object targetObject = app.getBean(interfaceClass);
					Method method = targetObject.getClass().getMethod(name, parameterTypes);
					Object obj = method.invoke(targetObject, args);
					if (obj == null)
					{
						f = ctx.writeAndFlush(NullWritable.nullWritable());
					}
					else
					{
						f = ctx.writeAndFlush(obj);
					}
					f.addListener(ChannelFutureListener.CLOSE);
				}
				catch (Exception e)
				{
					e.printStackTrace();
				}
				finally
				{
					f.addListener(ChannelFutureListener.CLOSE);
				}
			}
		});
	}

	public void setApplicationContext(ApplicationContext ctx)
		throws BeansException
	{
		this.app = ctx;
	}
}
